#include "exchange_obj.h"
#include "common/system_log.h"
#include "topology/TopoBuilder.hpp"
#include "topology/TopoCompound.hpp"
#include "topomesh/BRepMeshIncrementalMesh.hpp"
#include "io/OBJTool.hpp"
#include "common/system_log.h"
#include "utils/file_util.h"
#include "ExchangeTopoShape.h"

AMCAX_EXCHANGE_NAMESPACE_BEGIN

void ExchangeObj::ReadFromFilePath() 
{
    throw std::runtime_error("Not implemented");
}

void ExchangeObj::ReadFromFileStream() 
{
    throw std::runtime_error("Not implemented");
}

void ExchangeObj::Write(const std::vector<std::shared_ptr<ExchangeObject>>& exchange_shapes, const std::shared_ptr<ExchangeDocumentInstance> &exchangeDocumentInstance)
{
#ifdef AMCAX_OBJ_ENABLE
    ObjOutputParameter *parameter = dynamic_cast<ObjOutputParameter *>(GetExchangeParameter()) ;
    double linearDeflection = DEFAULT_LINEAR_DEFLECTION ;
    double angleDeflection = DEFAULT_ANGLE_DEFLECTION ;
    if (nullptr != parameter) {
        linearDeflection = parameter->GetLinearDeflection();
        linearDeflection = (linearDeflection > MAX_LINEAR_DEFLECTION)? MAX_LINEAR_DEFLECTION : linearDeflection ;
        linearDeflection = (linearDeflection < MIN_LINEAR_DEFLECTION)? MIN_LINEAR_DEFLECTION : linearDeflection ;
        
        angleDeflection = parameter->GetAngleDeflection();
        angleDeflection = (angleDeflection > MAX_LINEAR_DEFLECTION)? MAX_ANGLE_DEFLECTION : angleDeflection ;
        angleDeflection = (angleDeflection < MIN_LINEAR_DEFLECTION)? MIN_ANGLE_DEFLECTION : angleDeflection ;
    }
    LOG_INFO("linearDeflection:{}",linearDeflection) ;

    AMCAX::TopoBuilder builder;
    AMCAX::TopoCompound comp;
    builder.MakeCompound(comp);
    exchangeDocumentRootInstance_ = exchangeDocumentInstance ;
    ToPart() ;

    for (auto exData : exchangePartObjectList_) 
    {
        if (!exData->shape->GetShape().IsNull())
        {
            // AMCAX::TopoShape poundShape = comp;
            AMCAX::BRepMeshIncrementalMesh aMesh(exData->shape->GetShape(), linearDeflection, true, angleDeflection);
            builder.Add(comp, exData->shape->GetShape());
        }
    }

    // std::vector<std::shared_ptr<ExchangeObject>> flatShapes;
    // NestedExchangeShapeToFlat(flatShapes, exchange_shapes); 
    // for (auto &top_shape : exchange_shapes) {
    //     flatShapes.push_back(top_shape) ;
    //     NestedExchangeShapeToFlat(flatShapes, top_shape); 
    // }

    // for (auto exData : flatShapes) 
    // {
    //     if (!exData->shape->GetShape().IsNull())
    //     {
    //         // AMCAX::TopoShape poundShape = comp;
    //         AMCAX::BRepMeshIncrementalMesh aMesh(exData->shape->GetShape(), linearDeflection, true, angleDeflection);
    //         builder.Add(comp, exData->shape->GetShape());
    //     }
    // }

    // AMCAX::TopoShape poundShape = comp;
    // AMCAX::BRepMeshIncrementalMesh aMesh(poundShape, linearDeflection, true, angleDeflection);
    if (OUTPUT_FILE_TYPE::FILE_PATH == outputFileType_) {
        if (AMCAX::Exchange::file_util::is_file_exist(filePath_))
        {
            LOG_ERROR("file<{}> already exist",filePath_) ;
            return ;
        }
       AMCAX::OBJTool::WriteShape(comp, filePath_);
    }
    else if (OUTPUT_FILE_TYPE::FILE_OUTPUT_STREAM == outputFileType_) 
    {
        if(nullptr == outFileStream_) {
            LOG_ERROR("outFileStream_ is null") ;
            return  ;
        }
        // AMCAX::OBJTool::WriteShape(poundShape, *outFileStream_); TODO: How to write an obj into a stream
    }else {
        LOG_ERROR("output file type:{} is unknown",(int)outputFileType_) ;
        return ;
    }

    // AMCAX::OBJTool::WriteShape(poundShape, filePath_);
#endif
}


AMCAX_EXCHANGE_NAMESPACE_END